home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / mint104s.zoo / mint.src / dosfile.c < prev    next >
C/C++ Source or Header  |  1993-03-08  |  25KB  |  1,136 lines

  1. /*
  2. Copyright 1990,1991,1992 Eric R. Smith.
  3. Copyright 1992 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. /* DOS file handling routines */
  8.  
  9. #include "mint.h"
  10.  
  11. extern char temp1[];    /* see filesys.c */
  12.  
  13. static long do_dup P_((int,int));
  14. static void unselectme P_((PROC *));
  15.  
  16. /*
  17.  * first, some utility routines
  18.  */
  19.  
  20. FILEPTR *
  21. do_open(name, rwmode, attr, x)
  22.     const char *name;    /* file name */
  23.     int rwmode;    /* file access mode */
  24.     int attr;    /* TOS attributes for created files (if applicable) */
  25.     XATTR *x;    /* filled in with attributes of opened file */
  26. {
  27.     struct tty *tty;
  28.     fcookie dir, fc;
  29.     long devsp;
  30.     FILEPTR *f;
  31.     DEVDRV *dev;
  32.     long r;
  33.     XATTR xattr;
  34.     unsigned perm;
  35.     int creating;
  36.     extern FILESYS proc_filesys;
  37.  
  38. /* for special BIOS "fake" devices */
  39.     extern DEVDRV fakedev;
  40.  
  41.     TRACE(("do_open(%s)", name));
  42.  
  43. /*
  44.  * first step: get a cookie for the directory
  45.  */
  46.  
  47.     r = path2cookie(name, temp1, &dir);
  48.     if (r) {
  49.         mint_errno = (int)r;
  50.         DEBUG(("do_open(%s): error %ld", name, r));
  51.         return NULL;
  52.     }
  53.  
  54. /*
  55.  * second step: try to locate the file itself
  56.  */
  57.     r = relpath2cookie(&dir, temp1, follow_links, &fc, 0);
  58.  
  59. /*
  60.  * file found: this is an error if (O_CREAT|O_EXCL) are set
  61.  */
  62.  
  63.     if ( (r == 0) && ( (rwmode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ) ) {
  64.         DEBUG(("do_open(%s): file already exists",name));
  65.         mint_errno = EACCDN;
  66.         release_cookie(&fc);
  67.         release_cookie(&dir);
  68.         return NULL;
  69.     }
  70. /*
  71.  * file not found: maybe we should create it
  72.  * note that if r != 0, the fc cookie is invalid (so we don't need to
  73.  * release it)
  74.  */
  75.     if (r == EFILNF && (rwmode & O_CREAT)) {
  76.     /* check first for write permission in the directory */
  77.         r = (*dir.fs->getxattr)(&dir, &xattr);
  78.         if (r == 0) {
  79.             if (denyaccess(&xattr, S_IWOTH))
  80.                 r = EACCDN;
  81.         }
  82.         if (r) {
  83.             DEBUG(("do_open(%s): couldn't get "
  84.                   "write permission on directory",name));
  85.             mint_errno = (int)r;
  86.             release_cookie(&dir);
  87.             return NULL;
  88.         }
  89.         r = (*dir.fs->creat)(&dir, temp1,
  90.             (S_IFREG|DEFAULT_MODE) & (~curproc->umask), attr, &fc);
  91.         if (r) {
  92.             DEBUG(("do_open(%s): error %ld while creating file",
  93.                 name, r));
  94.             mint_errno = (int)r;
  95.             release_cookie(&dir);
  96.             return NULL;
  97.         }
  98.         creating = 1;
  99.     } else if (r) {
  100.         DEBUG(("do_open(%s): error %ld while searching for file",
  101.             name, r));
  102.         mint_errno = (int)r;
  103.         release_cookie(&dir);
  104.         return NULL;
  105.     } else {
  106.         creating = 0;
  107.     }
  108.  
  109. /*
  110.  * check now for permission to actually access the file
  111.  */
  112.     r = (*fc.fs->getxattr)(&fc, &xattr);
  113.     if (r) {
  114.         DEBUG(("do_open(%s): couldn't get file attributes",name));
  115.         mint_errno = (int)r;
  116.         release_cookie(&dir);
  117.         release_cookie(&fc);
  118.         return NULL;
  119.     }
  120. /*
  121.  * we don't do directories
  122.  */
  123.     if ( (xattr.mode & S_IFMT) == S_IFDIR ) {
  124.         DEBUG(("do_open(%s): file is a directory",name));
  125.         release_cookie(&dir);
  126.         release_cookie(&fc);
  127.         mint_errno = EFILNF;
  128.         return NULL;
  129.     }
  130.  
  131.     switch (rwmode & O_RWMODE) {
  132.     case O_WRONLY:
  133.         perm = S_IWOTH;
  134.         break;
  135.     case O_RDWR:
  136.         perm = S_IROTH|S_IWOTH;
  137.         break;
  138.     case O_EXEC:
  139.         perm = (fc.fs->fsflags & FS_NOXBIT) ? S_IROTH : S_IXOTH;
  140.         break;
  141.     case O_RDONLY:
  142.         perm = S_IROTH;
  143.         break;
  144.     default:
  145.         perm = 0;
  146.         ALERT("do_open: bad file access mode: %x", rwmode);
  147.     }
  148.     if (!creating && denyaccess(&xattr, perm)) {
  149.         DEBUG(("do_open(%s): access to file denied",name));
  150.         release_cookie(&dir);
  151.         release_cookie(&fc);
  152.         mint_errno = EACCDN;
  153.         return NULL;
  154.     }
  155.  
  156. /*
  157.  * an extra check for write access -- even the superuser shouldn't
  158.  * write to files with the FA_RDONLY attribute bit set (unless,
  159.  * we just created the file, or unless the file is on the proc
  160.  * file system and hence FA_RDONLY has a different meaning)
  161.  */
  162.     if ( !creating && (xattr.attr & FA_RDONLY) && fc.fs != &proc_filesys) {
  163.         if ( (rwmode & O_RWMODE) == O_RDWR ||
  164.              (rwmode & O_RWMODE) == O_WRONLY ) {
  165.             DEBUG(("do_open(%s): can't write a read-only file",
  166.                 name));
  167.             release_cookie(&dir);
  168.             release_cookie(&fc);
  169.             mint_errno = EACCDN;
  170.             return NULL;
  171.         }
  172.     }
  173.  
  174. /*
  175.  * if writing to a setuid or setgid file, clear those bits
  176.  */
  177.     if ( (perm & S_IWOTH) && (xattr.mode & (S_ISUID|S_ISGID)) ) {
  178.         xattr.mode &= ~(S_ISUID|S_ISGID);
  179.         (*fc.fs->chmode)(&fc, (xattr.mode & ~S_IFMT));
  180.     }
  181. /*
  182.  * If the caller asked for the attributes of the opened file, copy them over.
  183.  */
  184.     if (x) *x = xattr;
  185.  
  186. /*
  187.  * So far, so good. Let's get the device driver now, and try to
  188.  * actually open the file.
  189.  */
  190.     dev = (*fc.fs->getdev)(&fc, &devsp);
  191.     if (!dev) {
  192.         mint_errno = (int)devsp;
  193.         DEBUG(("do_open(%s): device driver not found",name));
  194.         release_cookie(&dir);
  195.         release_cookie(&fc);
  196.         return NULL;
  197.     }
  198.  
  199.     if (dev == &fakedev) {        /* fake BIOS devices */
  200.         f = curproc->handle[devsp];
  201.         if (!f) {
  202.             mint_errno = EIHNDL;
  203.             return 0;
  204.         }
  205.         f->links++;
  206.         release_cookie(&dir);
  207.         release_cookie(&fc);
  208.         return f;
  209.     }
  210.     if (0 == (f = new_fileptr())) {
  211.         release_cookie(&dir);
  212.         release_cookie(&fc);
  213.         mint_errno = ENSMEM;
  214.         return NULL;
  215.     }
  216.     f->links = 1;
  217.     f->flags = rwmode;
  218.     f->pos = 0;
  219.     f->devinfo = devsp;
  220.     f->fc = fc;
  221.     f->dev = dev;
  222.     release_cookie(&dir);
  223.  
  224.     r = (*dev->open)(f);
  225.     if (r < 0) {
  226.         DEBUG(("do_open(%s): device open failed with error %ld",
  227.             name, r));
  228.         mint_errno = (int)r;
  229.         f->links = 0;
  230.         release_cookie(&fc);
  231.         dispose_fileptr(f);
  232.         return NULL;
  233.     }
  234.  
  235. /* special code for opening a tty */
  236.     if (is_terminal(f)) {
  237.         extern struct tty default_tty;    /* in tty.c */
  238.  
  239.         tty = (struct tty *)f->devinfo;
  240.         if (tty->use_cnt == 0) {     /* first open for this device? */
  241.             *tty = default_tty;
  242.         }
  243.         tty->use_cnt++;
  244.     }
  245.     return f;
  246. }
  247.  
  248. /*
  249.  * helper function for do_close: this closes the indicated file pointer which
  250.  * is assumed to be associated with process p. The extra parameter is necessary
  251.  * because f_midipipe mucks with file pointers of other processes, so
  252.  * sometimes p != curproc.
  253.  *
  254.  * Note that the function changedrv() in filesys.c can call this routine.
  255.  * in that case, f->dev will be 0 to represent an invalid device, and
  256.  * we cannot call the device close routine.
  257.  */
  258.  
  259. long
  260. do_pclose(p, f)
  261.     PROC *p;
  262.     FILEPTR *f;
  263. {
  264.     long r = 0;
  265.  
  266.     if (!f) return EIHNDL;
  267.  
  268. /* if this file is "select'd" by this process, unselect it
  269.  * (this is just in case we were killed by a signal)
  270.  */
  271.  
  272. /* BUG? Feature? If media change is detected while we're doing the select,
  273.  * we'll never unselect (since f->dev is set to NULL by changedrv())
  274.  */
  275.     if (f->dev) {
  276.         (*f->dev->unselect)(f, (long)p, O_RDONLY);
  277.         (*f->dev->unselect)(f, (long)p, O_WRONLY);
  278.     }
  279.  
  280.     f->links--;
  281.  
  282. /* TTY manipulation must be done *before* calling the device close routine,
  283.  * since afterwards the TTY structure may no longer exist
  284.  */
  285.     if (is_terminal(f) && f->links <= 0) {
  286.         struct tty *tty = (struct tty *)f->devinfo;
  287.         tty->use_cnt--;
  288.         if (tty->use_cnt <= 0)
  289.             tty->pgrp = 0;
  290.         if (tty->use_cnt <= 0 && tty->xkey) {
  291.             kfree(tty->xkey);
  292.             tty->xkey = 0;
  293.         }
  294.     }
  295.  
  296.     if (f->dev) {
  297.         r = (*f->dev->close)(f, p->pid);
  298.         if (r) {
  299.             DEBUG(("close: device close failed"));
  300.         }
  301.     }
  302.     if (f->links <= 0) {
  303.         release_cookie(&f->fc);
  304.         dispose_fileptr(f);
  305.     }
  306.     return  r;
  307. }
  308.  
  309. long
  310. do_close(f)
  311.     FILEPTR *f;
  312. {
  313.     return do_pclose(curproc, f);
  314. }
  315.  
  316. long ARGS_ON_STACK
  317. f_open(name, mode)
  318.     const char *name;
  319.     int mode;
  320. {
  321.     int i;
  322.     FILEPTR *f;
  323.     PROC *proc;
  324.  
  325.     TRACE(("Fopen(%s, %x)", name, mode));
  326. #if O_GLOBAL
  327.     if (mode & O_GLOBAL) {
  328.         /* oh, boy! user wants us to open a global handle! */
  329.         proc = rootproc;
  330.     }
  331.     else
  332. #endif
  333.         proc = curproc;
  334.  
  335.     for (i = MIN_OPEN; i < MAX_OPEN; i++) {
  336.         if (!proc->handle[i])
  337.             goto found_for_open;
  338.     }
  339.     DEBUG(("Fopen(%s): process out of handles",name));
  340.     return ENHNDL;        /* no more handles */
  341.  
  342. found_for_open:
  343.     mode &= O_USER;        /* make sure the mode is legal */
  344.  
  345. /* note: file mode 3 is reserved for the kernel; for users, transmogrify it
  346.  * into O_RDWR (mode 2)
  347.  */
  348.     if ( (mode & O_RWMODE) == O_EXEC ) {
  349.         mode = (mode & ~O_RWMODE) | O_RDWR;
  350.     }
  351.  
  352.     f = do_open(name, mode, 0, (XATTR *)0);
  353.  
  354.  
  355.     if (!f) {
  356.         return m